#include "basic_tool.h"
#include <sys/stat.h>
#include <time.h>
#include <sys/timeb.h>

int BasicTool::Load_File(string& str, string filename)
{
  ifstream is;
  is.open(filename.c_str(), ios::binary);
  if (!is)
	{
	  cerr<<"open "<<filename<<" failed"<<endl;
	  return -1;
	}
  int length;
  char * buffer;

  // get length of file:
  is.seekg (0, ios::end);
  length = is.tellg();
  is.seekg (0, ios::beg);

  // allocate memory:
  buffer = new char [length];

  // read data as a block:
  is.read (buffer,length);
  is.close();
  str.assign(buffer, length);
  delete[] buffer;
  return 0;
}

int BasicTool::Load_File(char* & buffer, size_t& length, string filename)
{
  ifstream is;
  is.open(filename.c_str(), ios::binary);
  if (!is)
	{
	  cerr<<"open "<<filename<<" failed"<<endl;
	  return -1;
	}
  // get length of file:
  is.seekg (0, ios::end);
  length = is.tellg();
  is.seekg (0, ios::beg);

  // allocate memory:
  buffer = new char [length];

  // read data as a block:
  is.read (buffer,length);
  is.close();
  return 0;
}

int BasicTool::Dump_File(const string& str, string filename)
{
  ofstream os;
  os.open(filename.c_str(), ios::binary);
  if (!os)
	{
	  cerr<<"open "<<filename<<" failed"<<endl;
	  string foldername = filename.substr(0, filename.rfind('/'));
	  cout<<"create "<<foldername<<endl;
	  if (mkdir(foldername.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
		{
		  cerr<<"make "<<foldername<<" failed"<<endl;

		  return -1;
		}
	  cout<<"reopen "<<filename<<endl;
	  os.open(filename.c_str(), ios::binary);
	  if (!os)
		{
		  cerr<<"open "<<filename<<" failed again, give up"<<endl;
		}
	}
  os.write(str.c_str(), str.length());
  os.close();
  return 0;
}

string BasicTool::Strip(const string& str, char dem)
{
  string::size_type i = str.find(dem);
  assert(i != string::npos);
  string::size_type j = str.rfind(dem);
  assert(j != string::npos);
  string ret = str.substr(i+1, j-i-1);
  return ret;
}

int BasicTool::Load_RSA_Priv_Key(mpz_t * d, mpz_t * N, string filename)
{
  FILE * file;

  file = fopen(filename.c_str(), "r");
  if (file == NULL)
	{
	  cerr<<"load rsa key failed from"<<filename<<endl;
	  return -1;
	}
  gmp_fscanf(file, "d=%Zx\n", *d);
  gmp_fscanf(file, "N=%Zx\n", *N);
  fclose(file);
  return 0;
}

int BasicTool::Load_RSA_Pub_Key(mpz_t * e, mpz_t * N, mpz_t * g, string filename)
{
  FILE * file;

  file = fopen(filename.c_str(), "r");
  if (file == NULL)
	{
	  cerr<<"load rsa key failed from"<<filename<<endl;
	  return -1;
	}
  gmp_fscanf(file, "e=%Zx\n", *e);
  gmp_fscanf(file, "N=%Zx\n", *N);
  gmp_fscanf(file, "g=%Zx\n", *g);
  fclose(file);
  return 0;
}

int BasicTool::Load_DSA_Priv_Key(mpz_t * p, mpz_t *q, mpz_t *g, mpz_t *x, string filename)
{
  FILE * pfile;
  pfile = fopen(filename.c_str(), "r");
  if (pfile == NULL)
	{
	  cerr<<"load dsa key failed from"<<filename<<endl;
	  return -1;
	}
  gmp_fscanf(pfile, "%Zx\n", *p);
  gmp_fscanf(pfile, "%Zx\n", *q);
  gmp_fscanf(pfile, "%Zx\n", *g);
  gmp_fscanf(pfile, "%Zx\n", *x);
  fclose(pfile);
  return 0;
}

int BasicTool::Load_DSA_Pub_Key(mpz_t * p, mpz_t *q, mpz_t *g, mpz_t *y, string filename)
{
  FILE * pfile;
  pfile = fopen(filename.c_str(), "r");
  if (pfile == NULL)
	{
	  cerr<<"load dsa key failed from"<<filename<<endl;
	  return -1;
	}
  gmp_fscanf(pfile, "%Zx\n", *p);
  gmp_fscanf(pfile, "%Zx\n", *q);
  gmp_fscanf(pfile, "%Zx\n", *g);
  gmp_fscanf(pfile, "%Zx\n", *y);
  fclose(pfile);
  return 0;
}

int BasicTool::Load_IBE_Server_Key(pairing_t *pairing, element_t *P, element_t *Q, element_t *z, element_t *R, string filename)
{
  char param[1024];
  ifstream infile(filename.c_str());
  if (!infile)
	{
	  cerr<<"open "<<filename<<" failed"<<endl;
	  return -1;
	}
  size_t count, n;
  infile.read((char *)&count, sizeof(count));
  if (!count)
	{
	  pbc_die("input error");
	  return -2;
	}
  infile.read(param, count);
  pairing_init_set_buf(*pairing, param, count);
  
  unsigned char * data;
  element_init_G1(*P, *pairing);
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*P, data);
  delete [] data;

  element_init_G1(*Q, *pairing); 
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*Q, data);
  delete [] data;

  element_init_G1(*R, *pairing); 
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*R, data);
  delete [] data;

  element_init_Zr(*z, *pairing);//secret key
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*z, data);
  delete [] data;
  return 0;
}

int BasicTool::Load_IBE_Client_Key(pairing_t *pairing, element_t *P, element_t *Q, element_t *s, string filename)
{
  char param[1024];
  ifstream infile(filename.c_str());
  if (!infile)
	{
	  cerr<<"open "<<filename<<" failed"<<endl;
	  return -1;
	}
  size_t count, n;
  infile.read((char *)&count, sizeof(count));
  if (!count)
	{
	  pbc_die("input error");
	  return -2;
	}
  infile.read(param, count);
  pairing_init_set_buf(*pairing, param, count);
  
  unsigned char * data;
  element_init_G1(*P, *pairing);
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*P, data);
  delete [] data;

  element_init_G1(*Q, *pairing); 
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*Q, data);
  delete [] data;

  element_init_Zr(*s, *pairing);//secret key
  infile.read((char *)&n, sizeof(n));
  data = new unsigned char [n];
  infile.read((char *)data, n);
  element_from_bytes(*s, data);
  //element_printf("%B\n", *m_s);
  delete [] data;
  return 0;
}

void BasicTool::TimeStamp(unsigned long & milli)
{
  struct timeb t;
  ftime(&t);
  milli = t.time * 1000 + t.millitm;
}

string BasicTool::TimeStamp()
{
  struct timeb t;
  stringstream ss;
  ftime(&t);
  ss<<t.time<<":"<<t.millitm;
  return ss.str(); 
}

double BasicTool::F_Time(int s)
{
	double measure;
	static struct timeb tstart,tend;
	long tdiff;
	
	if (s == START) 
	  {
		ftime(&tstart);
		return(0);
	  }
	else
	  {
		ftime(&tend);
		tdiff=(long)tend.millitm-(long)tstart.millitm;
		measure=((double)(tend.time-tstart.time))*1000+((double)tdiff);
		return measure;			// in miliseconds
	  }
}

string BasicTool::ToLowercase(string& s)
{
  int (*pf)(int)=tolower; 
  transform(s.begin(), s.end(), s.begin(), pf); 
  return s;
}


void BasicTool::lTrim(string& s, string dem)
{
  string::size_type pos = s.find_first_not_of(dem);
  if(pos != 0) //if there are leading whitespaces erase them
   s.erase(0, pos);
}

void BasicTool::rTrim(string& s, string dem)
{
  string::size_type pos = s.find_last_not_of(dem);
  if(pos != string::npos)
	{
	  if (s.length()!=pos+1)//if there are trailing whitespaces erase them
		s.erase(pos+1);
	}
  else s="";
}
